package com.dingdang.controller;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.client.utils.StringUtils;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dingdang.config.AlipayConfig;
import com.dingdang.data.Result;
import com.dingdang.em.ResultEnum;
import com.dingdang.entity.TbAdvertise;
import com.dingdang.mapper.TbAdvertiseMapper;
import com.dingdang.utils.IdWorker;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 广告表
 * 前端控制器
 * </p>
 *
 * @author author
 * @since 2021-12-17
 */
@RestController
@RequestMapping("advertise")
@Api(value = "广告推送,管理")
public class TbAdvertiseController {
    @Resource
    private TbAdvertiseMapper tbAdvertiseMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String from;


    @GetMapping("get")
    @ApiOperation(value = "广告查询全部")
    public Result getInfo(HttpServletRequest request) {
        try {
            Map<String,Object>map = new HashMap<>();
            int status = 2;
            map.put("status",status);
            List<TbAdvertise> tbAdvertises = tbAdvertiseMapper.selectByMap(map);
            TbAdvertise tbAdvertise= (TbAdvertise) redisTemplate.boundValueOps("a").get();
            long time = tbAdvertise.getEndTime().getTime();
            Date date = new Date();
            long time1 = date.getTime();
            BigDecimal totalPrice = tbAdvertise.getTotalPrice();
            Integer price = Integer.valueOf(String.valueOf(totalPrice));
            if (time<time1 || price <=0){
                tbAdvertiseMapper.updateStatus(tbAdvertise.getId());
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper messageHelper = new MimeMessageHelper(message, true);
                messageHelper.setSubject("请尽快续费,或者不再展示该广告");
                messageHelper.setText("<table border='1'>"+
                        "<p>该商家:"+tbAdvertise.getSellerName()+"</p>"+
                        "<p>"+"请尽快续费,若不续费自动下架该广告"+"</p>"+
                        "</table>", true);
                //收件人
                messageHelper.setTo(tbAdvertise.getEmail());
                //发件人
                messageHelper.setFrom(from);
                javaMailSender.send(message);
            }
            String ip = null;
            try {
                //以下两个获取在k8s中，将真实的客户端IP，放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。
                ip = request.getHeader("authToken");
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("Proxy-Client-IP");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("WL-Proxy-Client-IP");
                }
                if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                }
                if ("0:0:0:0:0:0:0:1".equals(ip)) {
                    ip = "127.0.0.1";
                }
                if (ip.split(",").length > 1) {
                    ip = ip.split(",")[0];
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.err.println(ip);
            redisTemplate.boundValueOps("ip").set(ip);
            redisTemplate.boundValueOps("ip").expire(30,TimeUnit.MINUTES);
            Object ip1 = redisTemplate.boundValueOps("ip").get();
            if (!ip.equals(ip1)){
                tbAdvertiseMapper.updateInfo();
            }
            return Result.ok().setData(tbAdvertises);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }

    @PutMapping("add")
    @ApiOperation(value = "广告增加功能")
    @ApiImplicitParam(name = "tbAdvertise", value = "广告增加的实体类", required = true, paramType = "body")
    public Result addInfo(@RequestBody TbAdvertise tbAdvertise) {
        try {
            Integer f = tbAdvertise.getField();
            Map map1 = new HashMap<>();
            map1.put("field",f);
            List list = tbAdvertiseMapper.selectByMap(map1);
            if (list.size() !=0){
                return Result.ok().setData("该广告已经有排期");
            }else {
                Date startTime = tbAdvertise.getStartTime();
                Date endTime = tbAdvertise.getEndTime();
                Integer field = tbAdvertise.getField();
                Map<String, Object> map = new HashMap<>();
                if (field == 1) {
                    tbAdvertise.setTotalPrice(BigDecimal.valueOf(5000));
                } else if (field == 2) {
                    tbAdvertise.setTotalPrice(BigDecimal.valueOf(4000));
                } else if (field == 3) {
                    tbAdvertise.setTotalPrice(BigDecimal.valueOf(3000));
                } else if (field == 4) {
                    tbAdvertise.setTotalPrice(BigDecimal.valueOf(2000));
                } else if (field == 5) {
                    tbAdvertise.setTotalPrice(BigDecimal.valueOf(1000));
                }
                map.put("startTime", startTime);
                map.put("endTime", endTime);
                map.put("field", field);
                tbAdvertise.setStatus(0);
                tbAdvertise.setOrderId(new IdWorker().nextId());
                tbAdvertiseMapper.insert(tbAdvertise);
                redisTemplate.boundValueOps("a").set(tbAdvertise);
                redisTemplate.expire("a",endTime.getTime(), TimeUnit.MINUTES);
                return Result.ok().setData(tbAdvertise.getOrderId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR);
        }
    }

    @PostMapping("update")
    @ApiOperation(value = "广告修改功能")
    @ApiImplicitParam(name = "tbAdvertise", value = "修改广告的实体类", required = true, paramType = "body")
    public Result updateInfo(@RequestBody TbAdvertise tbAdvertise) {
        try {
            int update = tbAdvertiseMapper.updateById(tbAdvertise);
            if (update >= 1) {
                return Result.ok().setData(update);
            } else {
                return Result.response(ResultEnum.ERROR).setData(update);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }

    //根据Id删除
    @DeleteMapping("delete")
    @ApiOperation(value = "广告图片删除")
    @ApiImplicitParam(name = "id", value = "广告要删除的Id", required = true, paramType = "query")
    public Result delete(@RequestParam("id") Long id) {
        try {
            int delete = tbAdvertiseMapper.deleteById(id);
            if (delete != 0) {
                return Result.ok().setData(delete);
            } else {
                return Result.response(ResultEnum.ERROR).setData(delete);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }

    //根据Id批量删除
    @DeleteMapping("deleteByIds")
    @ApiOperation(value = "广告批量删除")
    @ApiImplicitParam(name = "id", value = "广告要删除的Id", required = true, paramType = "query")
    public Result deleteIds(@RequestParam("ids") Long[] ids) {
        try {
            int delete = tbAdvertiseMapper.deleteBatchIds(Arrays.asList(ids));
            if (delete != 0) {
                return Result.ok().setData(delete);
            } else {
                return Result.response(ResultEnum.ERROR).setData(delete);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }

    @PostMapping("findList")
    @ApiOperation(value = "分页查询图片")
    public Result findList() {
        try {
            QueryWrapper<TbAdvertise> query = new QueryWrapper<>();
            Page<TbAdvertise> page = new Page<>(1, 2);
            IPage<TbAdvertise> pictures = tbAdvertiseMapper.selectPage(page, query);
            List<TbAdvertise> records = pictures.getRecords();
            List<TbAdvertise> pictureDetailsCars = JSONObject.parseArray(JSONObject.toJSONString(records), TbAdvertise.class);
            return Result.ok().setData(pictureDetailsCars);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }


    @GetMapping
    @ApiOperation(value = "订单支付")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单号", required = true, paramType = "query"),
            @ApiImplicitParam(name = "orderPrice", value = "支付金额", required = true, paramType = "query"),
            @ApiImplicitParam(name = "ordername", value = "订单名称", required = false, paramType = "query"),
            @ApiImplicitParam(name = "orderbody", value = "描述", required = false, paramType = "query")
    })
    public String OrderPay(@RequestParam String orderId,
                           @RequestParam String orderPrice,
                           @RequestParam String ordername,
                           @RequestParam String orderbody
    ) {
            return alipayTradePagePay(orderId, orderPrice, ordername, orderbody);
    }


    @RequestMapping("alipayTradePagePay")
    @ResponseBody
    public String alipayTradePagePay(String WIDout_trade_no, String WIDtotal_amount, String WIDsubject, String WIDbody) {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);


        alipayRequest.setBizContent("{\"out_trade_no\":\"" + WIDout_trade_no + "\","
                + "\"total_amount\":\"" + WIDtotal_amount + "\","
                + "\"subject\":\"" + WIDsubject + "\","
                + "\"body\":\"" + WIDbody + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求
        String result = null;
        try {
            result = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        //输出 ,在jsp中,可以模仿我们的Controller层,然后我们的Controller,HTTPServerletResponse response.writer() @ResponseBody
        //在jsp中我们使用out.println来代替 response.writer() 和 @ResponseBody
        //out.println(result);
        return result;
    }

    @RequestMapping("notifyUrl")
    public String notifyUrl(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws Exception {
        System.out.println("z");

        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

        //——请在这里编写您的程序（以下代码仅作参考）——

	/* 实际验证过程建议商户务必添加以下校验：
	1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
	2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
	3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
	4、验证app_id是否为该商户本身。
	*/
        if (signVerified) {//验证成功
            System.out.println("异步回调验签成功>>>>>>>>>>");
            /*//商户订单号
            String out_t        rade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");*/
            if (trade_status.equals("TRADE_FINISHED")) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                System.out.println(1);
                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                //注意：
                System.out.println(2);
                //付款完成后，支付宝系统发送该交易状态通知
                // 根据商品id减库存 后发送mq 根据商品生成订单
                //id  添加数据  Order

            }
            //修改订单状态为已支付
            System.out.println(3);
            TbAdvertise tbAdvertise = (TbAdvertise) redisTemplate.boundValueOps("a").get();
            tbAdvertise.setStatus(2);
            LambdaUpdateWrapper<TbAdvertise> lambdaUpdate = new LambdaUpdateWrapper();
            lambdaUpdate.eq(TbAdvertise::getOrderId,out_trade_no).set(TbAdvertise::getStatus,"2");
            tbAdvertiseMapper.update(null,lambdaUpdate);
            //out.println("success");
            System.out.println("异步回调成功");
            System.out.println("商户订单号" + out_trade_no);
            System.out.println("支付宝交易号" + trade_no);
            System.out.println("交易状态" + trade_status);
            return "success";

        } else {//验证失败
            //out.println("fail");
            System.out.println("异步回调失败");
            return "nosuccess";

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }


    }


    //-----------------------------------------分割线------------------------------------------------------------------


    /**
     * 同步回调方法:当我们提交订单去支付的时候,我们需要拿着订单号,金额等信息,调用支付宝,请求数据
     * 支付宝就会给我们返回数据,支付宝返回的其实是一个表单,而且自动跳转到支付宝付款页面的表单,紧接着跳转到了支付页面
     * 扫码付款成功后,支付宝会调用我们的同步回调方法,和异步回调
     *
     * @param request
     * @param out_trade_no 商户订单号
     * @param trade_no     支付宝交易号
     * @param total_amount 付款金额
     * @return
     * @throws Exception
     */
    @RequestMapping("returnUrl")
    public String returnUrl(Model model, HttpServletRequest request, String out_trade_no, String trade_no, String total_amount) throws Exception {
        /* *
         * 功能：支付宝服务器同步通知页面
         * 日期：2017-03-30
         * 说明：
         * 以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
         * 该代码仅供学习和研究支付宝接口使用，只是提供一个参考。


         *************************页面功能说明*************************
         * 该页面仅做页面展示，业务逻辑处理请勿在该页面执行
         */
        System.out.println("f");
        //获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        //这就是数字签名的验证, 也称之为:验签
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
        System.out.println(5);
        //——请在这里编写您的程序（以下代码仅作参考）——
        if (signVerified) {
            /*//商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");

            out.println("trade_no:"+trade_no+"<br/>out_trade_no:"+out_trade_no+"<br/>total_amount:"+total_amount);*/

            // 存入payLog表数据
            System.out.println(6);
            System.out.println("同步回调成功");
            System.out.println("商户订单号:" + out_trade_no);
            System.out.println("支付宝交易号:" + trade_no);
            System.out.println("付款金额:" + total_amount);
        } else {
            //out.println("验签失败");
            System.out.println("同步回调失败:验签失败");
            return "error";
        }
        //——请在这里编写您的程序（以上代码仅作参考）——
        return "success";
    }
}
